import React from "react";
import { Input, Switch, Radio, InputNumber, message, Button } from "antd";
import { ArrowUpOutlined, ArrowDownOutlined, DeleteOutlined } from "@ant-design/icons";
import VFontAlignPicker from "../VFontAlignPicker";
import VCodeEditor from "../VCodeEditor";
import { customSorterConfigTemplate, componentExtraSetting } from "./config";
import { jsonUtils } from "utils";
import "./index.scss";

interface IColumns {
    title: string;
    type?: string;
    dataIndex: string;
    align: "left" | "right" | "center";
    sorter?: boolean | Function;
    width?: string | number;
    extra: {[key: string]: any};
    baseProps?: {[key: string]: any}
}
interface ITableColumnsSettingProps {
    columns: IColumns[];
    onChange: (value: IColumns[]) => void;
}
type SortType = "default" | "custom";
interface ITableColumnsSettingState {
    sorterType: SortType[];  // 排序类型
}
class TableColumnsSetting extends React.Component<ITableColumnsSettingProps, ITableColumnsSettingState> {
    state: ITableColumnsSettingState = {
        sorterType: []
    }
    componentDidMount(){
        const initSortType = this.props.columns.map(item => {
            const cons = item.constructor;
            return cons === Function ? "custom" : "default";
        });
        this.setState({sorterType: initSortType})
    }
    onChangeProps = (index: number, key: string, value: any, isNodeProps?: boolean) => {
        const { columns, onChange } = this.props;
        if(!isNodeProps){
            Reflect.set(columns[index], key, value);
        } else {
            Reflect.set(columns[index], "baseProps", {
                ...columns[index]?.baseProps,
                [key]: value
            })
        }
        onChange(columns);
    }
    changeColumnsPos = (index: number, direction: string) => {
        const { columns, onChange } = this.props;
        if(direction === "up"){
            columns[index] = columns.splice(index - 1, 1, columns[index])[0];
        } else if(direction === "down") {
            columns[index] = columns.splice(index + 1, 1, columns[index])[0];
        } else if(direction === "delete") {
            columns.splice(index, 1);
        }
        onChange(columns)
    }
    renderColumnItem = (column: IColumns, index: number) => {
        const { sorterType } = this.state;
        const { columns } = this.props;
        return (<div className="columns-item-setting">
            <div className="column-item-head">
                <span className="columns-key">第{index}列({column.dataIndex})</span>
                <div className="operate-btn">
                    <Button className="up-btn" size="small" type="primary" disabled={index === 0} onClick={() => this.changeColumnsPos(index, "up")}><ArrowUpOutlined /></Button>
                    <Button className="down-btn" size="small" type="primary" disabled={index === columns.length - 1} onClick={() => this.changeColumnsPos(index, "down")}><ArrowDownOutlined /></Button>
                    <Button className="delete-btn" size="small" type="primary" danger onClick={() => this.changeColumnsPos(index, "delete")}><DeleteOutlined /></Button>
                </div>
            </div>
            <ul className="columns-item-form">
                <li>
                    <label>列标题</label>
                    <div className="table-editor-wrapper">
                        <Input placeholder="列标题" value={column.title} onChange={(e) => this.onChangeProps(index, "title", e.target.value)}></Input>
                    </div>
                </li>
                <li>
                    <label>列键值</label>
                    <div className="table-editor-wrapper">
                        <Input placeholder="列键值" value={column.dataIndex} onChange={(e) => this.onChangeProps(index, "dataIndex", e.target.value || "")}></Input>
                    </div>
                </li>
                <li>
                    <label>对齐</label>
                    <div className="table-editor-wrapper">
                        <VFontAlignPicker value={column.align} onChange={(value) => this.onChangeProps(index, "align", value)} />
                    </div>
                </li>
                <li>
                    <label>排序</label>
                    <div className="table-editor-wrapper">
                        <Radio.Group value={sorterType[index]} onChange={(e) => {
                            sorterType[index] = e.target.value;
                            this.setState({sorterType: [...sorterType]});
                        }}>
                            <Radio value="default">默认</Radio>
                            <Radio value="custom">自定义</Radio>
                        </Radio.Group>
                        {
                            sorterType[index] === "default" && (<Switch checked={(column.sorter as any)} onChange={(checked) => this.onChangeProps(index, "sorter", checked)}></Switch>)
                        }
                        {
                            sorterType[index] === "custom" && <VCodeEditor btnText="自定义排序" btnExtra={{type: "primary"}} value={(jsonUtils.convertToString(`{sorter: ${column.sorter}}`)) || customSorterConfigTemplate} alertMessage={"自定义排序按照以下格式编写，内容和Antd Table表格自定义排序形式一致"} onChange={(code) => {
                                if(!code?.sorter) message.warn("自定义代码格式有误，请检查是否满足格式要求.");
                                this.onChangeProps(index, "sorter", code?.sorter)
                            }} />
                        }
                    </div>
                </li>
                <li>
                    <label>列宽</label>
                    <div className="table-editor-wrapper">
                        <InputNumber value={column.width} placeholder="列宽" onChange={(value) => this.onChangeProps(index, "width", value)} />
                    </div>
                </li>
                <li>
                    <label>自定义列属性</label>
                    <div className="table-editor-wrapper">
                        <VCodeEditor btnText="自定义列属性" btnExtra={{type: "primary"}} value={(jsonUtils.convertToString(column.extra)) || `{}`} alertMessage={"自定义列属性需要和Table.Column属性保持一致，请参照Antd Table.Column配置."} onChange={(code) => this.onChangeProps(index, "extra", code)} />
                    </div>
                </li>
                {
                    column?.type && componentExtraSetting[column?.type] && (Object.keys(componentExtraSetting[column.type]).map(key => {
                        const config = componentExtraSetting[(column.type as string)]?.[key];
                        const Component = config.component;
                        let value = column?.baseProps?.[key];
                        if(config?.type !== "basic"){
                            value = column?.baseProps?.[config?.type]?.[key];
                        }
                        if(config?.beforeTransform) {
                            value = config?.beforeTransform(value);
                        }
                        return <li>
                            {config.label && (<label>{config.label}</label>)}
                            <div className="table-editor-wrapper">
                                <Component {...config.props} value={value} onChange={(ev: any) => {
                                    let value = ev;
                                    let field = key;
                                    
                                    if(config.afterTransform){
                                        value = config.afterTransform(ev);
                                    }
                                    if(config.type !== "basic"){
                                        field = config.type;
                                        value = {
                                            ...column?.baseProps?.[field],
                                            [key]: value
                                        }
                                    };
                                    this.onChangeProps(index, field, value, true)
                                }} />
                            </div>
                        </li>
                    }))
                }
            </ul>
        </div>)
    }
    render(){
        const { columns } = this.props;
        return <div className="table-columns-setting-wrapper">
            {
                columns.map((item, index) => {
                    return this.renderColumnItem(item, index)
                })
            }
        </div>
    }
}

export default TableColumnsSetting;